﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Transactions;
using System.Windows.Forms;
using PayexpDAL;
using Utilities;
using System.Globalization;
using ExcelHandler;

namespace Moneymatters
{
    public partial class MainForm
    {
        #region Private Fields
        private bool _resultsExistBankStatementsView = false;
        private int _currentTotalNumberOfRecordsBankStatementsView = 0;
        private int _currentPageNumberBankStatementsView = 0;
        private int _currentLastPageNumberBankStatementsView = 0;
        private int _currentRecordsPerPageToUseBankStatementsView = 0;
        private int _currentPettyCashId = 0;
        private bool _resultRefreshNeededBankStatementsView;
        private FilterCriteria _currentFilterCriteriaBankStatementsView;
        private Dictionary<int, List<TransactionMaster>> _pagedResultBankStatementsView = new Dictionary<int, List<TransactionMaster>>();
        private Dictionary<int, List<DataGridViewRow>> _pagedResultDGViewRowsBankStatementsView = new Dictionary<int, List<DataGridViewRow>>();
        #endregion Private Fields

        #region Properties
        #endregion Properties

        #region Private Methods

        private void buttonExpandBankStatementsFilter_Click(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.Size = new Size(this.filterControlViewBankStatements.Width, 240);
            this.filterControlViewBankStatements.Location = new Point(this.filterControlViewBankStatements.Location.X, 40);

            this.dataGridViewViewBankStatements.Size = new Size(this.dataGridViewViewBankStatements.Width, 295);
            this.dataGridViewViewBankStatements.Location = new Point(this.dataGridViewViewBankStatements.Location.X, 280);
        }

        private void buttonCollapseBankStatementsFilter_Click(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.Size = new Size(this.filterControlViewBankStatements.Width, 18);
            this.filterControlViewBankStatements.Location = new Point(this.filterControlViewBankStatements.Location.X, 40);

            this.dataGridViewViewBankStatements.Size = new Size(this.dataGridViewViewBankStatements.Width, 510);
            this.dataGridViewViewBankStatements.Location = new Point(this.dataGridViewViewBankStatements.Location.X, 65);
        }
          
        private void buttonDisplayBankStatementsView_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            ResetBankStatementsView();
            SetResetChequeDetailsHeaderToPettyCashRollOverAmount(false);

            _currentFilterCriteriaBankStatementsView = this.filterControlViewBankStatements.GetFilterCriteria();
            if (_currentFilterCriteriaBankStatementsView.HasError)
            {
                MessageBox.Show(string.Join(Environment.NewLine, _currentFilterCriteriaBankStatementsView.ValidationErrorList.ToArray()), "Please correct your filter criteria", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                this._currentRecordsPerPageToUseBankStatementsView = this.NumberOfRecordsPerPage;
                FetchAndDisplayPagedResultsBankStatementsView();
            }
            this.Cursor = Cursors.Arrow;
        }

        private void buttonExportBankStatementsView_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            SetResetChequeDetailsHeaderToPettyCashRollOverAmount(false);
            if (!this.filterControlViewBankStatements.OnlyPettyCashFilterCriteriaSelected)
            {
                ResetBankStatementsView();
            }

            _currentFilterCriteriaBankStatementsView = this.filterControlViewBankStatements.GetFilterCriteria();
            if (_currentFilterCriteriaBankStatementsView.HasError)
            {
                MessageBox.Show(string.Join(Environment.NewLine, _currentFilterCriteriaBankStatementsView.ValidationErrorList.ToArray()), "Please correct your filter criteria", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                int numberOfRecordsPerPageToUse = this.NumberOfRecordsPerPage;
                ExportFilteredResult(this._currentFilterCriteriaBankStatementsView, this.progressBarExportFromBankStatementsView, numberOfRecordsPerPageToUse);
                ResetBankStatementsView();
            }
            this.Cursor = Cursors.Arrow;

        }

        private void buttonViewHistoryBankStatementsView_Click(object sender, EventArgs e)
        {
            ViewHistory(this.dataGridViewViewBankStatements);
        }

        private void buttonEditSelectedTransactionBankStatementsView_Click(object sender, EventArgs e)
        {
            if (this._resultRefreshNeededBankStatementsView && this.dataGridViewViewBankStatements.Rows.Count != 0)
            {
                DisplayRefreshViewMessage();
                return;
            }
            EditSelected(this.dataGridViewViewBankStatements);
        }

        private void DisplayPettyCashTransactions(List<int> transactionMasterIdList, int pettyCashId)
        {
            this.Cursor = Cursors.WaitCursor;
            ResetBankStatementsView();
            this._currentPettyCashId = pettyCashId;
            SetResetChequeDetailsHeaderToPettyCashRollOverAmount(true);

            this.filterControlViewBankStatements.Reset();
            this.filterControlViewBankStatements.TransactionMasterIdList.AddRange(transactionMasterIdList);
            
            _currentFilterCriteriaBankStatementsView = this.filterControlViewBankStatements.GetFilterCriteria();
            if (_currentFilterCriteriaBankStatementsView.HasError)
            {
                MessageBox.Show(string.Join(Environment.NewLine, _currentFilterCriteriaBankStatementsView.ValidationErrorList.ToArray()), "Please correct your filter criteria", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                this._currentRecordsPerPageToUseBankStatementsView = this.NumberOfRecordsPerPage;
                FetchAndDisplayPagedResultsBankStatementsView();
            }
            this.Cursor = Cursors.Arrow;

        }

        private void SetResetChequeDetailsHeaderToPettyCashRollOverAmount(bool set)
        {
            if (set)
            {
                this.dataGridViewViewBankStatements.Columns["dgvViewBankStatementRunningBalance"].HeaderText = "Roll Over Amount";
            }
            else
            {
                this.dataGridViewViewBankStatements.Columns["dgvViewBankStatementRunningBalance"].HeaderText = "Running Balance";
            }
        }

        private void FetchAndDisplayPagedResultsBankStatementsView()
        {
            if (this._currentFilterCriteriaBankStatementsView == null)
            {
                return;
            }

            List<TransactionMaster> result = new List<TransactionMaster>();
            if (_pagedResultBankStatementsView.ContainsKey(_currentPageNumberBankStatementsView))
            {
                result.AddRange(_pagedResultBankStatementsView[_currentPageNumberBankStatementsView]);
                if (result.Count > 0)
                {
                    this._resultsExistBankStatementsView = true;
                }
            }
            else
            {
                result.AddRange(
                        this.dataAccessHandlerCommonInstance.GetFilteredTransactionMasterList(_currentFilterCriteriaBankStatementsView, _currentPageNumberBankStatementsView, this._currentRecordsPerPageToUseBankStatementsView, out _currentTotalNumberOfRecordsBankStatementsView, MainForm.Context));

                if (result.Count > 0)
                {
                    this._resultsExistBankStatementsView = true;
                }
                else if (result.Count == 0 && !this._resultsExistBankStatementsView)
                {
                    ResetBankStatementsView();
                    MessageBox.Show("No results matched your filter criteria.", "No results", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    return;
                }

                int remainder = 0;
                this._currentLastPageNumberBankStatementsView = Math.DivRem(this._currentTotalNumberOfRecordsBankStatementsView, this._currentRecordsPerPageToUseBankStatementsView, out remainder);
                if (remainder > 0)
                {
                    this._currentLastPageNumberBankStatementsView = this._currentLastPageNumberBankStatementsView + 1;
                }

                if (this._currentLastPageNumberBankStatementsView == 1)
                {
                    this.buttonPreviousBankStatementsView.Enabled = false;
                    this.buttonNextBankStatementsView.Enabled = false;
                }

                if (result.Count > 0)
                {
                    if (_pagedResultBankStatementsView.Count == 5) // kepe just five pages in memory
                    {
                        int minPageNumber = _pagedResultBankStatementsView.Keys.Min();
                        int maxPageNumber = _pagedResultBankStatementsView.Keys.Max();

                        if (_currentPageNumberBankStatementsView > maxPageNumber)
                        {
                            _pagedResultBankStatementsView.Remove(minPageNumber);
                        }
                        else
                        {
                            _pagedResultBankStatementsView.Remove(maxPageNumber);
                        }
                    }

                    _pagedResultBankStatementsView.Add(_currentPageNumberBankStatementsView, result);
                }
            }

            // set current balance
            if (!result.Any(t => !t.IsActive) &&  
                (
                 (_currentFilterCriteriaBankStatementsView.OnlyReconciledRecords && _currentFilterCriteriaBankStatementsView.BankAccountsIdList.Count == 1) ||
                 (!result.Any(t => !t.BankDate.HasValue) && _currentFilterCriteriaBankStatementsView.BankAccountsIdList.Count == 1)
                )
               )
            {
                result = this.dataAccessHandlerCommonInstance.SetCurrentBalance(result, true, _currentFilterCriteriaBankStatementsView.BankAccountsIdList.First(), MainForm.Context);
                _currentFilterCriteriaBankStatementsView.RunningBalanceComputed = true;
            }

            if (this.filterControlViewBankStatements.OnlyPettyCashFilterCriteriaSelected && this._currentPettyCashId != 0)
            {
                result = this.dataAccessHandlerCommonInstance.SetRollOverAmount(result, this._currentPettyCashId, MainForm.Context);
            }

            PopulateBankStatementsGrid(result);
        }

        private void buttonClearViewBankStatementsGrid_Click(object sender, EventArgs e)
        {
            ResetBankStatementsView();
        }

        private void buttonPreviousBankStatementsView_Click(object sender, EventArgs e)
        {
            if (this._resultRefreshNeededBankStatementsView && this.dataGridViewViewBankStatements.Rows.Count != 0)
            {
                DisplayRefreshViewMessage();
                return;
            }
            
            this.Cursor = Cursors.WaitCursor;
            this. _currentPageNumberBankStatementsView = this._currentPageNumberBankStatementsView - 1;
            if (this._currentPageNumberBankStatementsView < 0)
            {
                this.buttonPreviousBankStatementsView.Enabled = false;
            }
            else if (_currentPageNumberBankStatementsView == 0)
            {
                this.buttonPreviousBankStatementsView.Enabled = false;
                FetchAndDisplayPagedResultsBankStatementsView();
            }
            else
            {
                FetchAndDisplayPagedResultsBankStatementsView();
            }

            this.buttonNextBankStatementsView.Enabled = true;
            this.Cursor = Cursors.Arrow;
        }

        private void buttonNextBankStatementsView_Click(object sender, EventArgs e)
        {
            if (this._resultRefreshNeededBankStatementsView && this.dataGridViewViewBankStatements.Rows.Count != 0)
            {
                DisplayRefreshViewMessage();
                return;
            }

            this.Cursor = Cursors.WaitCursor;
            _currentPageNumberBankStatementsView = _currentPageNumberBankStatementsView + 1;
            this.buttonPreviousBankStatementsView.Enabled = true;
            FetchAndDisplayPagedResultsBankStatementsView();
            if ((this._currentPageNumberBankStatementsView + 1) == this._currentLastPageNumberBankStatementsView)
            {
                this.buttonNextBankStatementsView.Enabled = false;
            }
            this.Cursor = Cursors.Arrow;
        }

        private void ResetBankStatementsView()
        {
            this._pagedResultBankStatementsView.Clear();
            this._pagedResultDGViewRowsBankStatementsView.Clear();
            this.dataGridViewViewBankStatements.Rows.Clear();
            this._currentTotalNumberOfRecordsBankStatementsView = 0;
            this._currentPageNumberBankStatementsView = 0;
            this._currentLastPageNumberBankStatementsView = 0;
            this._currentFilterCriteriaBankStatementsView = null;
            this.buttonPreviousBankStatementsView.Enabled = false;
            this.buttonNextBankStatementsView.Enabled = true;
            this._resultsExistBankStatementsView = false;
            this.labelCurentPageNumberDetailsBankStatementsView.Text = string.Empty;
            this.filterControlViewBankStatements.TransactionMasterIdList.Clear();
            this._resultRefreshNeededBankStatementsView = false;
            this._currentPettyCashId = 0;
        }

        private void PopulateBankStatementsGrid(List<TransactionMaster> transactionMasterList)
        {
            this.dataGridViewViewBankStatements.Rows.Clear();

            if (_pagedResultDGViewRowsBankStatementsView.ContainsKey(this._currentPageNumberBankStatementsView))
            {
                foreach (DataGridViewRow dgViewRow in _pagedResultDGViewRowsBankStatementsView[this._currentPageNumberBankStatementsView])
                {
                    this.dataGridViewViewBankStatements.Rows.Add(dgViewRow);
                }
            }
            else
            {
                List<DataGridViewRow> forCaching = new List<DataGridViewRow>();
                foreach (TransactionMaster transactionMasterEntry in transactionMasterList)
                {
                    this.dataGridViewViewBankStatements.Rows.Add();
                    int newRowIndex = this.dataGridViewViewBankStatements.Rows.Count - 1;
                    DataGridViewRow newRow = this.dataGridViewViewBankStatements.Rows[newRowIndex];

                    if (transactionMasterEntry.Head.Equals("head_expense"))
                    {
                        newRow.DefaultCellStyle.BackColor = Color.PaleVioletRed;
                    }
                    else
                    {
                        newRow.DefaultCellStyle.BackColor = Color.LightGreen;
                    }

                    if (!transactionMasterEntry.IsActive)
                    {
                        newRow.DefaultCellStyle.BackColor = Color.DimGray;
                    }

                    newRow.Cells["dgvViewBankStatementTransactionDate"].Value = transactionMasterEntry.TransactionDate.Get_DD_MONTH_YY_DateString();//.ToShortDateString();

                    if (transactionMasterEntry.BankDate.HasValue)
                    {
                        newRow.Cells["dgvViewBankStatementBankDate"].Value = transactionMasterEntry.BankDate.Value.Get_DD_MONTH_YY_DateString();
                    }

                    newRow.Cells["dgvViewBankStatementChequeDetails"].Value = transactionMasterEntry.GetConsolidatedChequeDetails();

                    newRow.Cells["dgvViewBankStatementTransactionBank"].Value = GetBankName(transactionMasterEntry.BankAccountsId);

                    newRow.Cells["dgvViewBankStatementAmount"].Value = transactionMasterEntry.TransactionAmount;

                    if (this.filterControlViewBankStatements.OnlyPettyCashFilterCriteriaSelected && this._currentPettyCashId != 0)
                    {
                        newRow.Cells["dgvViewBankStatementRunningBalance"].Value = transactionMasterEntry.RollOverAmount;
                    }
                    else if (this._currentFilterCriteriaBankStatementsView.RunningBalanceComputed)
                    {
                        newRow.Cells["dgvViewBankStatementRunningBalance"].Value = transactionMasterEntry.CurrentBalance;
                    }

                    newRow.Cells["dgvViewBankStatementNarration"].Value = transactionMasterEntry.Narration;

                    newRow.Cells["dgvViewBankStatementHeadDetails"].Value = transactionMasterEntry.GetHeadDetailsComplete();

                    newRow.Cells["dgvViewBankStatementExpenseApprovers"].Value = transactionMasterEntry.ExpenseApprovalDetails;

                    newRow.Cells["dgvViewBankStatementTransactionMode"].Value = transactionMasterEntry.TransactionModeValueDisplayName;

                    newRow.Cells["dgvViewBankStatementPrintLink"].Value = transactionMasterEntry.VoucherReceiptNumber.ToString();

                    foreach (DataGridViewCell cell in newRow.Cells)
                    {
                        cell.Style.WrapMode = DataGridViewTriState.True;
                    }

                    if (!transactionMasterEntry.IsActive)
                    {
                        DataGridViewCellStyle style = new DataGridViewCellStyle();
                        style.Font = new Font(dataGridViewViewBankStatements.Font.OriginalFontName, dataGridViewViewBankStatements.Font.Size, FontStyle.Strikeout);
                        if (transactionMasterEntry.Head.Equals("head_expense"))
                        {
                            style.BackColor = Color.PaleVioletRed;
                        }
                        else
                        {
                            style.BackColor = Color.LightGreen;
                        }


                        newRow.DefaultCellStyle.ApplyStyle(style);
                    }

                    forCaching.Add(newRow);

                    newRow.Tag = transactionMasterEntry;
                }

                if (this._pagedResultDGViewRowsBankStatementsView.Count == 5) // kepe just five pages in memory
                {
                    int minPageNumber = this._pagedResultDGViewRowsBankStatementsView.Keys.Min();
                    int maxPageNumber = this._pagedResultDGViewRowsBankStatementsView.Keys.Max();

                    if (_currentPageNumberBankStatementsView > maxPageNumber)
                    {
                        this._pagedResultDGViewRowsBankStatementsView.Remove(minPageNumber);
                    }
                    else
                    {
                        this._pagedResultDGViewRowsBankStatementsView.Remove(maxPageNumber);
                    }
                }

                this._pagedResultDGViewRowsBankStatementsView.Add(_currentPageNumberBankStatementsView, forCaching);
            }

            if (this.dataGridViewViewBankStatements.Rows.Count > 0)
            {
                this.dataGridViewViewBankStatements.Rows[0].Selected = true;

                this.dataGridViewViewBankStatements_Click(this.dataGridViewTransactions, null);

                this.labelCurentPageNumberDetailsBankStatementsView.Text = string.Format("Page {0}/{1}", (this._currentPageNumberBankStatementsView + 1), this._currentLastPageNumberBankStatementsView);
            }
        }

        private void dataGridViewViewBankStatements_Click(object sender, EventArgs e)
        {
            if (this.dataGridViewViewBankStatements.SelectedRows.Count == 0)
            {
                return;
            }

            DataGridViewRow selectedRow = dataGridViewViewBankStatements.SelectedRows[0]; // multi select not considered
            TransactionMaster transactionMaster = (TransactionMaster)selectedRow.Tag;

            selectedRow.DefaultCellStyle.SelectionBackColor = selectedRow.DefaultCellStyle.BackColor;
        }

        private void dataGridViewViewBankStatements_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView gridView = (DataGridView)sender;
            if (gridView.SelectedCells.Count > 0 && gridView.SelectedCells[0] as DataGridViewLinkCell != null)
            {
                DataGridViewLinkCell dataGridViewLinkCell = (DataGridViewLinkCell)gridView.SelectedCells[0];
                DataGridViewRow owningRow = dataGridViewLinkCell.OwningRow;
                if (owningRow.Tag as TransactionMaster != null)
                {
                    // call pdf method here
                    TransactionMaster transactionMaster = (TransactionMaster)owningRow.Tag;
                    if (transactionMaster.IsActive)
                    {
                        try
                        {
                            PDFCreator.CreateVoucher(transactionMaster);
                        }
                        catch
                        {
                            MessageBox.Show("There was a problem generating your voucher/ receipt. Please try again. If the problem persists, please contact your administrator to have this fixed.", "Could not generate document", MessageBoxButtons.OK, MessageBoxIcon.Error);
                            return;
                        }
                    }
                    else
                    {
                        MessageBox.Show("You cannot generate a receipt or voucher for a deleted transaction.", "Cannot generate", MessageBoxButtons.OK, MessageBoxIcon.Information);
                        return;
                    }
                }
            }
        }

        private void buttonToday_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.Today);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }

        private void buttonYesterday_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.Yesterday);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }

        private void buttonDayBeforeYesterday_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.DayBeforeYesterday);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }

        private void buttonThisWeek_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.ThisWeek);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }

        private void buttonLastWeek_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.LastWeek);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }

        private void buttonCurrentMonth_Click(object sender, EventArgs e)
        {
            DateTimeRange dateTimeRange = new DateTimeRange(DateRange.ThisMonth);
            this.filterControlViewBankStatements.SetDateRange(dateTimeRange.LowerRange, dateTimeRange.UpperRange);
            this.buttonExpandBankStatementsFilter_Click(null, null);
        }
        
        private void checkBoxOnlyReconciledRecordsBankStatementsView_CheckedChanged(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.OnlyReconciledRecords = this.checkBoxOnlyReconciledRecordsBankStatementsView.Checked;
            if (this.checkBoxOnlyReconciledRecordsBankStatementsView.Checked && this.checkBoxOnlyUnreconciledRecordsBankStatementsView.Checked)
            {
                this.checkBoxOnlyUnreconciledRecordsBankStatementsView.Checked = false;
            }
        }

        private void checkBoxOnlyUnreconciledRecordsBankStatementsView_CheckedChanged(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.OnlyUnreconciledRecords = this.checkBoxOnlyUnreconciledRecordsBankStatementsView.Checked;
            if (this.checkBoxOnlyUnreconciledRecordsBankStatementsView.Checked && this.checkBoxOnlyReconciledRecordsBankStatementsView.Checked)
            {
                this.checkBoxOnlyReconciledRecordsBankStatementsView.Checked = false;
            }
        }

        private void checkBoxOnlyIncomeRecordsBankStatementsView_CheckedChanged(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.OnlyIncomeRecords = this.checkBoxOnlyIncomeRecordsBankStatementsView.Checked;
            if (this.checkBoxOnlyIncomeRecordsBankStatementsView.Checked && this.checkBoxOnlyExpenseRecordsBankStatementsView.Checked)
            {
                this.checkBoxOnlyExpenseRecordsBankStatementsView.Checked = false;
            }
        }

        private void checkBoxOnlyExpenseRecordsBankStatementsView_CheckedChanged(object sender, EventArgs e)
        {
            this.filterControlViewBankStatements.OnlyExpenseRecords = this.checkBoxOnlyExpenseRecordsBankStatementsView.Checked;
            if (this.checkBoxOnlyExpenseRecordsBankStatementsView.Checked && this.checkBoxOnlyIncomeRecordsBankStatementsView.Checked)
            {
                this.checkBoxOnlyIncomeRecordsBankStatementsView.Checked = false;
            }
        }

        

        #endregion Private Methods

        #region Public Methods

        #endregion Public Methods
    }
}